package com.java8.stream;

import com.java8.lambda.bean.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

public class StreamCenterApiTest {

    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99),
            new Employee("李四", 38, 5555.55),
            new Employee("王五", 50, 6666.99),
            new Employee("赵六", 16, 8888.99),
            new Employee("田七", 8, 7777.99)

    );


    //中间操作
    /**
     * 筛选切片
     * filter -- 接收Lambda,从流中排除某些元素。
     * limit -- 截断流,使其元素不超过给定数量。
     * skip(n) -- 跳过元素，返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
     * distinct -- 筛选,通过新流所生成元素的hashCode()和equals()去除重复元素。
     */
    /**
     * Stream的中间操作
     * 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!
     * 而在终止操作时一次性全部处理，称为"惰性求值".
     */

    //内部迭代: 迭代操作由Stream API 完成
    @Test
    public void test1() {
        //中间操作:不会执行任何操作
        //进行过滤之后的中间操作，还会返回一个新stream流
        Stream<Employee> employeeStream = employees.stream().filter(e -> e.getAge() > 35);

        //终止操作:才会一次性执行全部的内容,即"惰性求值"
        //必须进行终止操作,Stream流才真正结束
        employeeStream.forEach(System.out::println);
    }

    //外部迭代: 通过迭代器进行循环
    @Test
    public void test2() {
        Iterator<Employee> iterator = employees.iterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }


    @Test
    public void test3() {
        //limit:使其元素不超过给定的数量，也叫短路操作
        employees.stream().filter(e -> {
            System.out.println("短路!");
            return e.getMoney() > 5000;

        }).limit(2).forEach(System.out::println);

    }

    @Test
    public void test4() {
        //skip:跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补。
        //distinct: 根据元素的hashCode和equals()去除重复元素，要想去除重复元素，要给元素生成hashCode()和equals()
        employees.stream().filter(e -> e.getMoney() > 5000).skip(2).distinct().forEach(System.out::println);
    }


    /**
     * 映射
     * map ---- 接收Lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
     * flatMap ---- 接收一个函数作为参数,将流中的每个值都换成另一个流，然后把所有流连接成一个流。
     */

    @Test
    public void test5() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");

        list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);

        employees.stream().map(Employee::getAge).forEach(System.out::println);

        Stream<Stream<Character>> stream = list.stream().map(StreamCenterApiTest::filterCharacter);

        stream.forEach((s) -> {
            s.forEach(System.out::println);
        });

        System.out.println("----------------------------------------------------------------");

        Stream<Character> characterStream = list.stream().flatMap(StreamCenterApiTest::filterCharacter);
        characterStream.forEach(System.out::println);

    }


    /**
     * Character类
     * Character类用于对单个字符进行操作
     * Character类在对象中包装一个基本类型char的值
     * char类型的包装类
     */
    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for (Character character : str.toCharArray()) {
            list.add(character);
        }
        return list.stream();
    }


    //中间操作

    /**
     * 排序
     * sorted() -- 自然排序
     * sorted(Comparator com) -- 定制排序
     */
    @Test
    public void test7() {
        List<String> list = Arrays.asList("ccc", "aaa", "bbb", "ddd", "eee");

        //自然排序
        System.out.println("自然排序");
        list.stream().sorted().forEach(System.out::println);


        //定制排序
        System.out.println("定制排序");
        employees.stream().sorted((o1, o2) -> {
                    if (o1.getAge().equals(o2.getAge())) {
                        return o1.getName().compareTo(o2.getName());
                    } else {
                        return o1.getAge().compareTo(o2.getAge());
                    }
                }
        ).forEach(System.out::println);
    }


}
